#ifndef GPIOCONTROLLER_H
#define GPIOCONTROLLER_H

#include <QObject>
#include <QLoggingCategory>
#include <gpiod.h>
#include <unordered_map>
#include "autoSettinghelp.h"
Q_DECLARE_LOGGING_CATEGORY(gpioController)

class GpioController : public QObject
{
    Q_OBJECT
    Q_PROPERTY(bool gpioDO1 READ gpioDO1 WRITE setGpioDO1 NOTIFY gpioDO1Changed)
    Q_PROPERTY(bool gpioDO2 READ gpioDO2 WRITE setGpioDO2 NOTIFY gpioDO2Changed)
    Q_PROPERTY(bool gpioDO3 READ gpioDO3 WRITE setGpioDO3 NOTIFY gpioDO3Changed)
    Q_PROPERTY(bool gpioDO4 READ gpioDO4 WRITE setGpioDO4 NOTIFY gpioDO4Changed)
    Q_PROPERTY(bool gpioDO5 READ gpioDO5 WRITE setGpioDO5 NOTIFY gpioDO5Changed)
    Q_PROPERTY(bool gpioDO6 READ gpioDO6 WRITE setGpioDO6 NOTIFY gpioDO6Changed)
    Q_PROPERTY(bool gpioDO7 READ gpioDO7 WRITE setGpioDO7 NOTIFY gpioDO7Changed)
    Q_PROPERTY(bool gpioDO8 READ gpioDO8 WRITE setGpioDO8 NOTIFY gpioDO8Changed)
    Q_PROPERTY(bool gpioDO9 READ gpioDO9 WRITE setGpioDO9 NOTIFY gpioDO9Changed)
    Q_PROPERTY(bool gpioDI1 READ gpioDI1 NOTIFY gpioDI1Changed)
    Q_PROPERTY(bool gpioDI2 READ gpioDI2 NOTIFY gpioDI2Changed)
    Q_PROPERTY(bool gpioDI3 READ gpioDI3 NOTIFY gpioDI3Changed)
    Q_PROPERTY(bool gpioDI4 READ gpioDI4 NOTIFY gpioDI4Changed)
    Q_PROPERTY(bool gpioDI5 READ gpioDI5 NOTIFY gpioDI5Changed)
public:
    enum PilotLampStatus
    {
        LAMP_YELLOW,
        LAMP_GREEN,
        LAMP_RED
    };

    static  GpioController &getInstance();
    AUTO_SETTING_PROPERTY(GpioController , int, gpioversion, 1)

    void pilotLampYellow();
    void pilotLampGreen();
    void pilotLampRed();
    void pilotLampBuzzer();
    Q_INVOKABLE void plcStart();
    void plcStop();
    PilotLampStatus  pilotLampStatus_ = LAMP_YELLOW;

    bool gpioDO1() const;
    void setGpioDO1(bool value);

    bool gpioDO2() const;
    void setGpioDO2(bool value);

    bool gpioDO3() const;
    void setGpioDO3(bool value);

    bool gpioDO4() const;
    void setGpioDO4(bool value);

    bool gpioDO5() const;
    void setGpioDO5(bool value);

    bool gpioDO6() const;
    void setGpioDO6(bool value);

    bool gpioDO7() const;
    void setGpioDO7(bool value);

    bool gpioDO8() const;
    void setGpioDO8(bool value);

    bool gpioDO9() const;
    void setGpioDO9(bool value);

    bool gpioDI1() const;
    bool gpioDI2() const;
    bool gpioDI3() const;
    bool gpioDI4() const;
    bool gpioDI5() const;

signals:
    void gpioDO1Changed();
    void gpioDO2Changed();
    void gpioDO3Changed();
    void gpioDO4Changed();
    void gpioDO5Changed();
    void gpioDO6Changed();
    void gpioDO7Changed();
    void gpioDO8Changed();
    void gpioDO9Changed();

    void gpioDI1Changed();
    void gpioDI2Changed();
    void gpioDI3Changed();
    void gpioDI4Changed();
    void gpioDI5Changed();

    void infrared1trigger();
    void infrared2trigger();
    void shortageGrigger();
    void inplaceGrigger();
    void replenishmentGrigger();
    void gpioDI4Sign();

private:
    explicit GpioController(QObject *parent = nullptr);
    ~GpioController();


    std::unordered_map<int, gpiod_chip *> chips;
    struct GpioLine {
        struct gpiod_chip *chip;
        struct gpiod_line *line;
    };
    bool isRunning = false;
    GpioLine doLines[9];
    GpioLine diLines[5];
    bool diValues[5];



    int setupGpio();
    void monitorInputs();
    GpioLine getGpioLine(const QString &gpioString);
    int parseGpioLine(const QString &gpioString);
    int parseGpioChip(const QString &gpioString);
    void handleEvent(int line_index);
    void processEvents(gpiod_line_bulk &event_bulk, int startIndex, int endIndex);
    void monitorGPIO2();
    void monitorGPIO4();

    QSettings setting;
};

#endif // GPIOCONTROLLER_H
